package cz.uhk.max.matrix;

import static org.junit.Assert.assertEquals;
import java.util.List;
import org.junit.Before;
import org.junit.Test;

import cz.uhk.max.exceptions.EquationException;
import cz.uhk.max.matrix.IEquation;
import cz.uhk.max.matrix.impl.EquationImpl;
import cz.uhk.max.matrix.impl.MatrixDaoImpl;
import cz.uhk.max.matrix.IMatrixDao;

public class EquationImplTestWithBound {
	private IEquation equation;
	private IMatrixDao dao;
	private Matrix A;
	private Matrix B;
	private Matrix lowerBound;
	private Matrix upperBound;

	@Before
	public void setUp() throws Exception {
		A = new Matrix(4, 3);
		B = new Matrix(4, 3);
		lowerBound = new Matrix(3, 1);
		upperBound = new Matrix(3, 1);
		A.setCol(0, 0, Long.parseLong("876"));
		A.setCol(0, 1, Long.parseLong("58"));
		A.setCol(0, 2, Long.parseLong("454"));

		A.setCol(1, 0, Long.parseLong("783"));
		A.setCol(1, 1, Long.parseLong("784"));
		A.setCol(1, 2, Long.parseLong("926"));

		A.setCol(2, 0, Long.parseLong("810"));
		A.setCol(2, 1, Long.parseLong("131"));
		A.setCol(2, 2, Long.parseLong("368"));

		A.setCol(3, 0, Long.parseLong("395"));
		A.setCol(3, 1, Long.parseLong("189"));
		A.setCol(3, 2, Long.parseLong("462"));

		B.setCol(0, 0, Long.parseLong("395"));
		B.setCol(0, 1, Long.parseLong("158"));
		B.setCol(0, 2, Long.parseLong("197"));

		B.setCol(1, 0, Long.parseLong("462"));
		B.setCol(1, 1, Long.parseLong("590"));
		B.setCol(1, 2, Long.parseLong("908"));

		B.setCol(2, 0, Long.parseLong("395"));
		B.setCol(2, 1, Long.parseLong("731"));
		B.setCol(2, 2, Long.parseLong("110"));

		B.setCol(3, 0, Long.parseLong("395"));
		B.setCol(3, 1, Long.parseLong("491"));
		B.setCol(3, 2, Long.parseLong("232"));

		equation = new EquationImpl(A, B, Long.parseLong("999"));
		dao = new MatrixDaoImpl();

	}

	@Test
	public void orderSides() throws EquationException {
		Matrix bound = new Matrix(3, 1);
		EquationImpl eq = new EquationImpl((EquationImpl) equation);
		bound.setCol(0, 0, Long.parseLong("100"));
		bound.setCol(1, 0, Long.parseLong("200"));
		bound.setCol(2, 0, Long.parseLong("300"));
		eq.orderSides(bound);
		assertEquals(eq.getA().getCol(0, 1).getValue(), 58);
		assertEquals(eq.getB().getCol(3, 2).getValue(), 232);
	}
//	@Test
//	public void indexOfRowWithMax() throws EquationException{
//		Long i = equation.indexOfRowWithMax(new TreeMatrix(A), new TreeMatrix(B));
//		assertEquals(i,(long) 1);
//	}
	public void solutionWithLowerBound1() {
		lowerBound.setCol(0, 0, Long.parseLong("396"));
		lowerBound.setCol(1, 0, Long.parseLong("999"));
		lowerBound.setCol(2, 0, Long.parseLong("395"));
		List<Matrix> sol = equation.solutionsWithLowerBoundForOneRow(A
				.getRows().get(0), B.getRows().get(0), lowerBound);

		assertEquals(sol, null);
	}

	@Test
	public void solutionWithLowerBound2() {
		lowerBound.setCol(0, 0, Long.parseLong("394"));
		lowerBound.setCol(1, 0, Long.parseLong("999"));
		lowerBound.setCol(2, 0, Long.parseLong("395"));
		List<Matrix> sol = equation.solutionsWithLowerBoundForOneRow(A
				.getRows().get(0), B.getRows().get(0), lowerBound);

		assertEquals(sol.size(), 1);
		assertEquals(sol.get(0).getCol(0, 0).getValue(), 395);
		assertEquals(sol.get(0).getCol(1, 0).getValue(), 999);
		assertEquals(sol.get(0).getCol(2, 0).getValue(), 395);
	}

	@Test
	public void solutionWithLowerBound3() {
		lowerBound.setCol(0, 0, Long.parseLong("394"));
		lowerBound.setCol(1, 0, Long.parseLong("999"));
		lowerBound.setCol(2, 0, Long.parseLong("394"));
		List<Matrix> sol = equation.solutionsWithLowerBoundForOneRow(A
				.getRows().get(0), B.getRows().get(0), lowerBound);

		assertEquals(sol.size(), 1);
		assertEquals(sol.get(0).getCol(0, 0).getValue(), 394);
		assertEquals(sol.get(0).getCol(1, 0).getValue(), 999);
		assertEquals(sol.get(0).getCol(2, 0).getValue(), 394);
	}

	@Test
	public void solutionWithLowerBound4() {
		lowerBound.setCol(0, 0, Long.parseLong("50"));
		lowerBound.setCol(1, 0, Long.parseLong("59"));
		lowerBound.setCol(2, 0, Long.parseLong("50"));
		List<Matrix> sol = equation.solutionsWithLowerBoundForOneRow(A
				.getRows().get(0), B.getRows().get(0), lowerBound);

		// System.out.println(sol.size());
		// System.out.println(sol.get(0).getCol(0, 0).getValue() + "-");
		// System.out.println(sol.get(0).getCol(1, 0).getValue() + "-");
		// System.out.println(sol.get(0).getCol(2, 0).getValue());
		// System.out.println(" ");
		// System.out.println(sol.get(1).getCol(0, 0).getValue() + "-");
		// System.out.println(sol.get(1).getCol(1, 0).getValue() + "-");
		// System.out.println(sol.get(1).getCol(2, 0).getValue());
		// System.out.println(" ");

		assertEquals(sol.size(), 2);
		assertEquals(sol.get(0).getCol(0, 0).getValue(), 59);
		assertEquals(sol.get(0).getCol(1, 0).getValue(), 59);
		assertEquals(sol.get(0).getCol(2, 0).getValue(), 50);

		assertEquals(sol.get(1).getCol(0, 0).getValue(), 50);
		assertEquals(sol.get(1).getCol(1, 0).getValue(), 59);
		assertEquals(sol.get(1).getCol(2, 0).getValue(), 59);
	}

	@Test
	public void solutionWithUpperBound() {
		upperBound.setCol(0, 0, Long.parseLong("890"));
		upperBound.setCol(1, 0, Long.parseLong("890"));
		upperBound.setCol(2, 0, Long.parseLong("890"));
		Matrix sol = equation.solutionWithUpperBoundForOneRow(A.getRows()
				.get(0), B.getRows().get(0), upperBound);
		assertEquals(sol.getCol(0, 0).getValue(), 395);
		assertEquals(sol.getCol(1, 0).getValue(), 890);
		assertEquals(sol.getCol(2, 0).getValue(), 395);
	}

	@Test
	public void solutionWithUpperBound2() {
		upperBound.setCol(0, 0, Long.parseLong("875"));
		upperBound.setCol(1, 0, Long.parseLong("875"));
		upperBound.setCol(2, 0, Long.parseLong("875"));
		Matrix sol = equation.solutionWithUpperBoundForOneRow(A.getRows()
				.get(0), B.getRows().get(0), upperBound);
		assertEquals(sol.getCol(0, 0).getValue(), 395);
		assertEquals(sol.getCol(1, 0).getValue(), 875);
		assertEquals(sol.getCol(2, 0).getValue(), 395);
	}

	@Test
	public void solutionWithUpperBound3() {
		upperBound.setCol(0, 0, Long.parseLong("450"));
		upperBound.setCol(1, 0, Long.parseLong("450"));
		upperBound.setCol(2, 0, Long.parseLong("450"));
		Matrix sol = equation.solutionWithUpperBoundForOneRow(A.getRows()
				.get(0), B.getRows().get(0), upperBound);
		assertEquals(sol.getCol(0, 0).getValue(), 395);
		assertEquals(sol.getCol(1, 0).getValue(), 450);
		assertEquals(sol.getCol(2, 0).getValue(), 395);
	}

	@Test
	public void solutionWithUpperBound4() {
		upperBound.setCol(0, 0, Long.parseLong("390"));
		upperBound.setCol(1, 0, Long.parseLong("900"));
		upperBound.setCol(2, 0, Long.parseLong("390"));
		Matrix sol = equation.solutionWithUpperBoundForOneRow(A.getRows()
				.get(0), B.getRows().get(0), upperBound);
		assertEquals(sol.getCol(0, 0).getValue(), 390);
		assertEquals(sol.getCol(1, 0).getValue(), 900);
		assertEquals(sol.getCol(2, 0).getValue(), 390);
	}

	@Test
	public void solutionWithUpperBound5() {
		Row r1 = new Row(3);
		Row r2 = new Row(3);
		r1.getCols().get(0).setValue(Long.parseLong("8"));
		r1.getCols().get(1).setValue(Long.parseLong("5"));
		r1.getCols().get(2).setValue(Long.parseLong("9"));

		r2.getCols().get(0).setValue(Long.parseLong("11"));
		r2.getCols().get(1).setValue(Long.parseLong("8"));
		r2.getCols().get(2).setValue(Long.parseLong("4"));

		upperBound.setCol(0, 0, Long.parseLong("5"));
		upperBound.setCol(1, 0, Long.parseLong("9"));
		upperBound.setCol(2, 0, Long.parseLong("3"));

		Matrix sol = equation.solutionWithUpperBoundForOneRow(r1, r2,
				upperBound);
		assertEquals(sol.getCol(0, 0).getValue(), 5);
		assertEquals(sol.getCol(1, 0).getValue(), 5);
		assertEquals(sol.getCol(2, 0).getValue(), 3);
	}

	public void setUpperBound(Matrix upperBound) {
		this.upperBound = upperBound;
	}

	public Matrix getUpperBound() {
		return upperBound;
	}

}